package pe.com.rimac.portal.service.facturacion.impl;

import java.io.ByteArrayInputStream;
import java.rmi.RemoteException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.lang.Validate;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import pe.com.rimac.portal.common.config.ServiceConfig;
import pe.com.rimac.portal.common.exception.ServiceException;
import pe.com.rimac.portal.service.facturacion.BusquedaPersonaService;
import pe.com.rimac.portal.service.facturacion.modelo.ResultadoBusqueda;
import pe.com.rimac.portal.service.facturacion.trama.BusquedaPersonaRequest;
import pe.com.rimac.portal.service.facturacion.trama.Header;

import com.rimac.wsbpm.personas.ejb.facade.proxy.PersonaFacadeProxy;

/**
 * @author Synopsis S.A
 *
 */
public class BusquedaPersonaServiceImpl implements BusquedaPersonaService
{
	private static final String CODIGO_RESPUESTA = "CODIGO";
	private static final String MENSAJE_RESPUESTA = "MENSAJE";
	private static final String CODIGO_EXITO = "0";
	private static final String PERSONA = "PERSONA";
	private static final String NUMID = "NUMID";
	private static final String NOMBRE = "NOMBRE";
	private static final String APELLIDO_PATERNO = "APEPAT";
	private static final String APELLIDO_MATERNO = "APEMAT";
	private static final String NOMBRE_COMPANIA = "NOMCOM";
	private static final String TIPO_DOCUMENTO = "CODTIPDOC";
	private static final String NUMERO_DOCUMENTO = "NUMIDDOC";
	private static final String DIRECCION = "DIREC";
	private static final String TELEFONO = "TELEF1";
	private static final String ANEXO = "ANEX1";
	
	private PersonaFacadeProxy port;
	
	/**
	 * @param serviceConfig
	 */
	public BusquedaPersonaServiceImpl(ServiceConfig serviceConfig)
	{
		this.port = new PersonaFacadeProxy();
		this.port.setEndpoint(serviceConfig.getProperty("facturacion.persona.ws.url"));
	}
	
	/**
	 * @see pe.com.rimac.portal.service.facturacion.BusquedaPersonaService#buscarPersona(java.lang.String, java.lang.String)
	 */
	@Override
	public ResultadoBusqueda buscarPersona(String tipoDocumento, String numeroDocumento) throws ServiceException
	{
		validarDatos(tipoDocumento, numeroDocumento);
		Header header = prepararHeader(numeroDocumento);
		BusquedaPersonaRequest request = new BusquedaPersonaRequest(header);
		request.setTipoDocumento(tipoDocumento);
		request.setNumeroDocumento(numeroDocumento);
		String response = invoke(request);
		return procesarResponse(response);
	}
	
	/**
	 * @param numeroDocumento
	 * @return
	 */
	private Header prepararHeader(String numeroDocumento)
	{
		Header header = new Header();
		header.setIdTransaccion("35480");
		header.setToken(numeroDocumento);
		header.setId("06");
		return header;
	}
	
	/**
	 * @param request
	 * @return
	 */
	private String invoke(BusquedaPersonaRequest request)
	{
		try
		{
			return this.port.buscarPersona(request.build());
		}
		catch (RemoteException e)
		{
			throw new ServiceException("Ocurrio un error al buscar personas", e);
		}
	}
	
	/**
	 * @param response
	 * @return
	 */
	private ResultadoBusqueda procesarResponse(String response)
	{
		Document xml = obtenerXML(response);
		return obtenerResultadoBusqueda(xml);
	}
	
	/**
	 * @param xml
	 * @return
	 */
	private ResultadoBusqueda obtenerResultadoBusqueda(Document xml)
	{
		xml.getDocumentElement().normalize();
		NodeList errorCodeNode = xml.getElementsByTagName(CODIGO_RESPUESTA);
		NodeList errorMessageNode = xml.getElementsByTagName(MENSAJE_RESPUESTA);
		Element errorCode = (Element) errorCodeNode.item(0);
		Element errorMessage = (Element) errorMessageNode.item(0);
		
		ResultadoBusqueda resultado = null;
		
		if (CODIGO_EXITO.equals(errorCode.getTextContent()))
		{
			NodeList nodes = xml.getElementsByTagName(PERSONA);
			for (int i = 0; i < nodes.getLength(); i++)
			{
				Element element = (Element) nodes.item(i);
				if (element.getNodeType() == Node.ELEMENT_NODE)
				{
					NodeList childnodes = element.getChildNodes();
					resultado = new ResultadoBusqueda();
					for (int j = 0; j < childnodes.getLength(); j++)
					{
						Node e = (Node) childnodes.item(j);
						if (e.getNodeType() == Node.ELEMENT_NODE)
						{
							Element elem = (Element) e;
							if (NUMID.equals(elem.getNodeName()))
							{
								resultado.setNumId(elem.getTextContent().trim());
							}
							else if(NOMBRE.equals(elem.getNodeName()))
							{
								resultado.setNombre(elem.getTextContent().trim());
							}
							else if(APELLIDO_PATERNO.equals(elem.getNodeName()))
							{
								resultado.setApellidoPaterno(elem.getTextContent().trim());
							}
							else if(APELLIDO_MATERNO.equals(elem.getNodeName()))
							{
								resultado.setApellidoMaterno(elem.getTextContent().trim());
							}
							else if(NOMBRE_COMPANIA.equals(elem.getNodeName()))
							{
								resultado.setNombreCompania(elem.getTextContent().trim());
							}
							else if(TIPO_DOCUMENTO.equals(elem.getNodeName()))
							{
								resultado.setTipoDocumento(elem.getTextContent().trim());
							}
							else if(NUMERO_DOCUMENTO.equals(elem.getNodeName()))
							{
								resultado.setNumeroDocumento(elem.getTextContent().trim());
							}
							else if(DIRECCION.equals(elem.getNodeName()))
							{
								resultado.setDireccion(elem.getTextContent().trim());
							}
							else if(TELEFONO.equals(elem.getNodeName()))
							{
								resultado.setTelefono(elem.getTextContent().trim());
							}
							else if(ANEXO.equals(elem.getNodeName()))
							{
								resultado.setAnexo(elem.getTextContent().trim());
							}
						}
					}
				}
			}
			return resultado;
		}
		throw new ServiceException("Ocurrio un error al momento de realizar la busqueda de personas. Error: '"
				+ errorCode.getTextContent() + "' - '" + errorMessage.getTextContent() + "'");
	}
	
	/**
	 * @param xmlAsString
	 * @return
	 */
	private Document obtenerXML(String xmlAsString)
	{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(false);
		DocumentBuilder builder;
		Document xml = null;
		// Se cambia el encoding antes
		xmlAsString = xmlAsString.replace("UTF-8", "ISO-8859-1");
		try
		{
			builder = factory.newDocumentBuilder();
			xml = builder.parse(new ByteArrayInputStream(xmlAsString.getBytes()));
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return xml;
	}
	
	private void validarDatos(String tipoDocumento, String numeroDocumento)
	{
		Validate.notNull(tipoDocumento);
		Validate.notEmpty(tipoDocumento);
		Validate.notNull(numeroDocumento);
		Validate.notEmpty(numeroDocumento);
	}
}